//
//  NSObject+ModelAnalytical.m
//

#import "NSObject+ModelAnalytical.h"
#import <objc/runtime.h>

@implementation NSObject (ModelAnalytical)

- (instancetype)initWithParameter:(NSDictionary *)parameter
{
    self = [self init];

    if (self) {
        u_int outCount;
        objc_property_t *methods = class_copyPropertyList([self class], &outCount);

        NSDictionary *types = [self propertiesWithEncodedTypes];
        
        for (int i = 0; i < outCount; i++) {
            objc_property_t objc_oneProp = methods[i];
            NSString *key = [NSString stringWithCString:property_getName(objc_oneProp) encoding:NSUTF8StringEncoding];
            
            id value = [parameter objectForKey:key];

            if ([key isEqualToString:@"Id"]) {
                value = [parameter objectForKey:@"id"];
            }

            if ([value isKindOfClass:[NSNull class]] || !value) {
                continue;
            }

            for (NSString *oneProp in types)
            {

                if ([key isEqualToString:oneProp]) {
                    NSString *propType = types[oneProp];
                    if ([propType isEqualToString:@"@\"NSDictionary\""]) {
                        if ([value isKindOfClass:[NSDictionary class]]) {
                            
                            [self setValue:value forKey:key];
                        }
                        continue;
                    }else if ([propType isEqualToString:@"@\"NSArray\""]) {
                        if ([value isKindOfClass:[NSArray class]]) {
                            [self setValue:value forKey:key];
                        }
                        continue;
                    }else if ([propType isEqualToString:@"@\"NSNumber\""]) {
                        if ([value isKindOfClass:[NSNumber class]]) {
                            [self setValue:value forKey:key];
                        } else if ([value isKindOfClass:[NSString class]]) {
                            NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
                            [self setValue:[nf numberFromString:value] forKey:key];
                        }
                        
                        continue;
                    }else {
                        
                        if ([value isKindOfClass:[NSString class]]) {
                            [self setValue:value forKey:key];
                        } else if ([value isKindOfClass:[NSNumber class]]) {
                            NSNumber *number = (NSNumber *)value;
                            [self setValue:number.stringValue forKey:key];
                        } else if ([value respondsToSelector:@selector(description)]) {
                            if (![@"<null>" isEqualToString:[value description]]) {
                                [self setValue:@"" forKey:key];
                            }
                        }
                        
                        continue;
                    }
                }
            }
        }
    }

    return self;
}

- (NSDictionary *)propertiesWithEncodedTypes
{
    // Recurse up the classes, but stop at NSObject. Each class only reports its own properties, not those inherited from its superclass
    NSMutableDictionary *theProps = [NSMutableDictionary dictionary];

    unsigned int outCount;
    objc_property_t *propList = class_copyPropertyList([self class], &outCount);

    if (!outCount) {
        propList = class_copyPropertyList([self superclass], &outCount);
    }

    // Loop through properties and add declarations for the create
    for (int i = 0; i < outCount; i++) {
        objc_property_t oneProp = propList[i];
        NSString *propName = [NSString stringWithUTF8String:property_getName(oneProp)];
        NSString *attrs = [NSString stringWithUTF8String:property_getAttributes(oneProp)];

        // Read only attributes are assumed to be derived or calculated
        if ([attrs rangeOfString:@",R,"].location == NSNotFound) {
            NSArray *attrParts = [attrs componentsSeparatedByString:@","];

            if (attrParts != nil) {
                if ([attrParts count] > 0) {
                    NSString *propType = [[attrParts objectAtIndex:0] substringFromIndex:1];
                    [theProps setObject:propType forKey:propName];
                }
            }
        }
    }

    free(propList);

    return theProps;
}

- (void)valueWithParameter:(NSDictionary *)parameter
{
    NSArray *property = [self property];

    NSDictionary *types = [self propertiesWithEncodedTypes];
    
    for (id keyT in parameter) {
        if ([property containsObject:keyT]||[keyT isEqualToString:@"id"]) {
            id value = [parameter objectForKey:keyT];

            if ([value isKindOfClass:[NSNull class]] || !value) {
                [self setValue:@"" forKey:keyT];
                continue;
            }

            for (NSString *oneProp in types)
            {
                NSString * key =keyT;
                if ([keyT isEqualToString:@"id"]) {
                    key = @"Id";
                }
                
                if ([key isEqualToString:oneProp]) {
                    NSString *propType = types[oneProp];
                    if ([propType isEqualToString:@"@\"NSDictionary\""]) {
                        if ([value isKindOfClass:[NSDictionary class]]) {
                            [self setValue:value forKey:key];
                        }
                        continue;
                    }else if ([propType isEqualToString:@"@\"NSArray\""]) {
                        if ([value isKindOfClass:[NSArray class]]) {
                            [self setValue:value forKey:key];
                        }
                        continue;
                    }else if ([propType isEqualToString:@"@\"NSNumber\""]) {
                        if ([value isKindOfClass:[NSNumber class]]) {
                            [self setValue:value forKey:key];
                        } else if ([value isKindOfClass:[NSString class]]) {
                            NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
                            [self setValue:[nf numberFromString:value] forKey:key];
                        }
                        
                        continue;
                    }else {
                        if ([value isKindOfClass:[NSString class]]) {
                            [self setValue:value forKey:key];
                        } else if ([value isKindOfClass:[NSNumber class]]) {
                            NSNumber *number = (NSNumber *)value;
                            [self setValue:number.stringValue forKey:key];
                        } else if ([value respondsToSelector:@selector(description)]) {
                            if (![@"<null>" isEqualToString:[value description]]) {
                                //[self setValue:[value description] forKey:key];
                                [self setValue:@"" forKey:key];
                            }
                        }
                        
                        continue;
                    }
                }
            }
        }
    }
}

- (NSArray *)property
{
    u_int outCount;
    objc_property_t *methods = class_copyPropertyList([self class], &outCount);

    NSMutableArray *property = [NSMutableArray array];

    for (int i = 0; i < outCount; i++) {
        objc_property_t objc_oneProp = methods[i];
        NSString *key = [NSString stringWithCString:property_getName(objc_oneProp) encoding:NSUTF8StringEncoding];
        [property addObject:key];
    }

    return property;
}

- (id)getValueOfKey:(NSString *)key{
    
    id value;
    
    unsigned int propsCount;
    objc_property_t *props = class_copyPropertyList([self class], &propsCount);//获得属性列表
    for(int i = 0;i < propsCount; i++){
        objc_property_t prop = props[i];
        NSString *propName = [NSString stringWithUTF8String:property_getName(prop)];//获得属性的名称
        if ([propName isEqualToString:key]) {
           return value = [self valueForKey:propName];//kvc读值
        }
    }
    return @"";
}


- (NSDictionary*)objectToDic{
    NSMutableDictionary *dic = [NSMutableDictionary dictionary];
    unsigned int propsCount;
    objc_property_t *props = class_copyPropertyList([self class], &propsCount);//获得属性列表
    for(int i = 0;i < propsCount; i++){
        objc_property_t prop = props[i];
        NSString *propName = [NSString stringWithUTF8String:property_getName(prop)];//获得属性的名称
        id value = [self valueForKey:propName];//kvc读值
        if(value == nil){
            value = @"";
        }else{
            value = [self getObjectInternal:value];//自定义处理数组，字典，其他类
        }
        
        if ([propName isEqualToString:@"Id"]) {
            propName = @"id";
        }
        
        [dic setObject:[NSString stringWithFormat:@"%@",value] forKey:propName];
    }
    return dic;
}

- (NSDictionary*)objectToDicNor{
    NSMutableDictionary *dic = [NSMutableDictionary dictionary];
    unsigned int propsCount;
    objc_property_t *props = class_copyPropertyList([self class], &propsCount);//获得属性列表
    for(int i = 0;i < propsCount; i++){
        objc_property_t prop = props[i];
        NSString *propName = [NSString stringWithUTF8String:property_getName(prop)];//获得属性的名称
        id value = [self valueForKey:propName];//kvc读值
        if(value != nil){
            value = [self getObjectInternal:value];//自定义处理数组，字典，其他类
        }else{
            
            continue;
        }
        
        if ([propName isEqualToString:@"Id"]) {
            propName = @"id";
        }
        
        [dic setObject:[NSString stringWithFormat:@"%@",value] forKey:propName];
    }
    return dic;
}


- (id)getObjectInternal:(id)obj{
    if([obj isKindOfClass:[NSString class]] || [obj isKindOfClass:[NSNumber class]] || [obj isKindOfClass:[NSNull class]]) {
        return obj;
    }
    if([obj isKindOfClass:[NSArray class]]) {
        NSArray *objarr = obj;
        NSMutableArray *arr = [NSMutableArray arrayWithCapacity:objarr.count];
        for(int i = 0;i < objarr.count; i++) {
            [arr setObject:[self getObjectInternal:[objarr objectAtIndex:i]] atIndexedSubscript:i];
        }
        return arr;
    }
    if([obj isKindOfClass:[NSDictionary class]]) {
        NSDictionary *objdic = obj;
        NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithCapacity:[objdic count]];
        for(NSString *key in objdic.allKeys){
            [dic setObject:[self getObjectInternal:[objdic objectForKey:key]] forKey:key];
        }
        return dic;
    }
    return [self objectToDic];
}

- (NSString *)requestDicToString{
    
    NSError * error;
    NSData * data = [NSJSONSerialization dataWithJSONObject:self options:NSJSONWritingPrettyPrinted error:&error];
    NSString * str = [[[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] stringByReplacingOccurrencesOfString:@"\n" withString:@""] stringByReplacingOccurrencesOfString:@" " withString:@""];
    
    return str;
}

@end
